package com.huonan.test.test2;

import cn.hutool.bloomfilter.BitMapBloomFilter;
import cn.hutool.bloomfilter.BloomFilter;
import cn.hutool.bloomfilter.bitMap.BitMap;
import cn.hutool.bloomfilter.bitMap.LongMap;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.Digester;
import com.huonan.utils.DateHelper;
import com.huonan.utils.MD5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.Md5Crypt;
import org.junit.Test;
import org.roaringbitmap.RoaringBitmap;

import java.io.UnsupportedEncodingException;

/**
 * @Description TODO
 * @Author lxp
 * @Date 2022/6/8 下午3:36
 * @Version V1.0
 **/
@Slf4j
public class BoolFilter {
    private void testBitMap() {
        BitMap bitMap = new LongMap();
        long a = 200000000L;
        DateHelper.MonitorUtil.start();
        System.out.println("start");
        for (long i = 0; i <= a; i++) {
            bitMap.add(i);
        }

        DateHelper.MonitorUtil.finish("存储耗时");
        DateHelper.MonitorUtil.start();
        for (int m = 0; m < 1; m++) {
            for (long i = 1; i <= a; i++) {
                if (!bitMap.contains(i)) {
                    System.out.println("误判：" + i + "不存在");
                }
            }
        }
        for (long m = a + 1; m <= a + 1000000; m++) {
            if (bitMap.contains(m)) {
                System.out.println("误判：" + m + "存在");
            }
        }
        DateHelper.MonitorUtil.finish("判断耗时");
        DateHelper.MonitorUtil.start();
        BloomFilter filter = new BitMapBloomFilter(5);

        for (long i = 0; i < a; i++) {
            filter.add("www.test" + i);
        }
        DateHelper.MonitorUtil.finish("存储耗时");
        DateHelper.MonitorUtil.start();

        int c = 0;
        for (long i = 0; i < a; i++) {
            if (!filter.contains("www.test" + i)) {
                c++;
            }
        }
        for (long m = a + 1; m <= a + 100000; m++) {
            if (filter.contains("www.test" + m)) {
                System.out.println("误判：" + m + "存在");
            }
        }
        DateHelper.MonitorUtil.finish("查询耗时");

        System.out.println("误判:");
    }


    public void testRoaring() {
        //向rr中添加1、2、3、1000四个数字
        RoaringBitmap rr = RoaringBitmap.bitmapOf(1, 2, 3, 1000);
        //创建RoaringBitmap rr2
        RoaringBitmap rr2 = new RoaringBitmap();
        //向rr2中添加10000-12000共2000个数字
        rr2.add(10000, 12000);
        //返回第3个数字是1000，第0个数字是1，第1个数字是2，则第3个数字是1000
        rr.select(3);
        //返回value = 2 时的索引为 1。value = 1 时，索引是 0 ，value=3的索引为2
        rr.rank(2);
        //判断是否包含1000
        rr.contains(1000); // will return true
        //判断是否包含7
        rr.contains(7); // will return false

        //两个RoaringBitmap进行or操作，数值进行合并，合并后产生新的RoaringBitmap叫rror
        RoaringBitmap rror = RoaringBitmap.or(rr, rr2);
        //rr与rr2进行位运算，并将值赋值给rr
        rr.or(rr2);
        //判断rror与rr是否相等，显然是相等的
        boolean equals = rror.equals(rr);
        if (!equals) {
            throw new RuntimeException("bug");
        }
        // 查看rr中存储了多少个值，1,2,3,1000和10000-12000，共2004个数字
        long cardinality = rr.getCardinality();
        System.out.println(rr2.getCardinality());
        System.out.println(cardinality);
        //遍历rr中的value
        // for (int i : rr) {
        //     System.out.println(i);
        // }
        // //这种方式的遍历比上面的方式更快
        // rr.forEach((Consumer<? super Integer>) i -> {
        //     System.out.println(i.intValue());
        // });
    }

    @Test
    public void testRoaringPerformance() throws UnsupportedEncodingException {
        String str = "17447848";
        long dataSize = 3 * 10000L;
        // md5.digest
        String s1 = Md5Crypt.apr1Crypt(str);
        String encryption = MD5Util.encryption(str);
        String s = DigestUtil.md5Hex(str);
        byte[] bytes = DigestUtils.md5(StringUtils.getBytesUtf8(str));
        String s2 = DigestUtils.md5Hex(str);

        if (s.equals(s1)&&s.equals(encryption)) {
            log.info("\n=====MD5====");
            log.info(String.valueOf(s.equals(s1)&&s.equals(encryption)));
        }
        Digester md5 = new Digester(DigestAlgorithm.MD5);

//        RoaringBitmap rr2 = new RoaringBitmap();
//        DateHelper.MonitorUtil.start();
//        for (long i = 0; i < dataSize; i++) {
//            String newStr = str + "_" + i;
//            try {
//                byte[] bytes = newStr.getBytes("UTF-8");
//                int i1 = HashUtil.cityHash32(bytes);
//                // log.info(newStr + "\n" + String.valueOf(i1));
//                rr2.add(i1);
//            } catch (UnsupportedEncodingException e) {
//                throw new RuntimeException(e);
//            }
//        }
//        DateHelper.MonitorUtil.finish(" \nRoaringBitmap 存储：" + rr2.getCardinality() / 10000 + "w 耗时：");
//        DateHelper.MonitorUtil.start();
//        int count = 0;
//        for (long i = dataSize + 1; i < dataSize + 10000; i++) {
//            if (!rr2.contains((int) i)) {
//                count++;
//            }
//        }
//        // int s1 = rr2.select(845777536);
//        String selectStr = str + "_" + 99 * 10000;
//        int cityHash32 = HashUtil.cityHash32(selectStr.getBytes("UTF-8"));
//        DateHelper.MonitorUtil.start();
//
//        boolean contains = rr2.contains(cityHash32);
//        DateHelper.MonitorUtil.finish(" 检索耗时：");
//
//        // log.info("s1:{}",s1);
//        log.info("是否存在:{}", contains);
//
//        System.out.println("误判:" + count);
//
//        DateHelper.MonitorUtil.finish(" \nRoaringBitmap 查询：" + "  耗时：");

    }
}
